/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-06-17 14:51:38
 * @LastEditTime: 2021-08-13 13:06:41
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */

#ifndef BSP_ARCH_ARMV8_AARCH32_CP15
#define BSP_ARCH_ARMV8_AARCH32_CP15

#include "ft_types.h"

#define __get_cp(cp, op1, Rt, CRn, CRm, op2) __asm__ volatile("MRC p" #cp ", " #op1 ", %0, c" #CRn ", c" #CRm ", " #op2 \
                                                              : "=r"(Rt)                                                \
                                                              :                                                         \
                                                              : "memory")
#define __set_cp(cp, op1, Rt, CRn, CRm, op2) __asm__ volatile("MCR p" #cp ", " #op1 ", %0, c" #CRn ", c" #CRm ", " #op2 \
                                                              :                                                         \
                                                              : "r"(Rt)                                                 \
                                                              : "memory")
#define __get_cp64(cp, op1, Rt, CRm) __asm__ volatile("MRRC p" #cp ", " #op1 ", %Q0, %R0, c" #CRm \
                                                      : "=r"(Rt)                                  \
                                                      :                                           \
                                                      : "memory")
#define __set_cp64(cp, op1, Rt, CRm) __asm__ volatile("MCRR p" #cp ", " #op1 ", %Q0, %R0, c" #CRm \
                                                      :                                           \
                                                      : "r"(Rt)                                   \
                                                      : "memory")

/* Instruction Synchronization Barrier */
#define ISB() __asm__ __volatile__("isb" \
                                   :     \
                                   :     \
                                   : "memory")

/* Data Synchronization Barrier */
#define DSB() __asm__ __volatile__("dsb" \
                                   :     \
                                   :     \
                                   : "memory")

/* Data Memory Barrier */
#define DMB() __asm__ __volatile__("dmb" \
                                   :     \
                                   :     \
                                   : "memory")

/* CP15 operations */
#define MTCP(rn, v) __asm__ __volatile__( \
    "mcr " rn "\n"                        \
    :                                     \
    : "r"(v));

#define MFCP(rn) ({       \
    u32 rval = 0U;        \
    __asm__ __volatile__( \
        "mrc " rn "\n"    \
        : "=r"(rval));    \
    rval;                 \
})

#define MFCPSR() ({       \
    u32 rval = 0U;        \
    __asm__ __volatile__( \
        "mrs	%0, cpsr\n"  \
        : "=r"(rval));    \
    rval;                 \
})

#define MTCPSR(v) __asm__ __volatile__( \
    "msr	cpsr,%0\n"                     \
    :                                   \
    : "r"(v)                            \
    : "cc")

/* The next two CP15 register accesses below have been deprecated in favor
 * of the new dsb and dmb instructions in Cortex A53.
 */
#define FREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0,  c7, c10, 4"
#define FREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0,  c7, c10, 5"

#define FREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0,  c7, c11, 1"

#define FREG_CP15_NOP2 "p15, 0, %0,  c7, c13, 1"

#define FREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0,  c7, c14, 1"
#define FREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0,  c7, c14, 2"

/* The CP15 register access below has been deprecated in favor of the new
 * isb instruction in Cortex A53.
 */
#define FREG_CP15_INST_SYNC_BARRIER "p15, 0, %0,  c7,  c5, 4"
#define FREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0,  c7,  c5, 6"

#define FREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0,  c7,  c6, 1"
#define FREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0,  c7,  c6, 2"

#define FREG_CP15_VA_TO_PA_CURRENT_0 "p15, 0, %0,  c7,  c8, 0"
#define FREG_CP15_VA_TO_PA_CURRENT_1 "p15, 0, %0,  c7,  c8, 1"
#define FREG_CP15_VA_TO_PA_CURRENT_2 "p15, 0, %0,  c7,  c8, 2"
#define FREG_CP15_VA_TO_PA_CURRENT_3 "p15, 0, %0,  c7,  c8, 3"

#define FREG_CP15_VA_TO_PA_OTHER_0 "p15, 0, %0,  c7,  c8, 4"
#define FREG_CP15_VA_TO_PA_OTHER_1 "p15, 0, %0,  c7,  c8, 5"
#define FREG_CP15_VA_TO_PA_OTHER_2 "p15, 0, %0,  c7,  c8, 6"
#define FREG_CP15_VA_TO_PA_OTHER_3 "p15, 0, %0,  c7,  c8, 7"

#define FREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0,  c7, c10, 1"
#define FREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0,  c7, c10, 2"

/* C0 Register defines */
#define FREG_CP15_MAIN_ID "p15, 0, %0,  c0,  c0, 0"
#define FREG_CP15_CACHE_TYPE "p15, 0, %0,  c0,  c0, 1"
#define FREG_CP15_TCM_TYPE "p15, 0, %0,  c0,  c0, 2"
#define FREG_CP15_TLB_TYPE "p15, 0, %0,  c0,  c0, 3"
#define FREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0,  c0,  c0, 5"

#define FREG_CP15_PROC_FEATURE_0 "p15, 0, %0,  c0,  c1, 0"
#define FREG_CP15_PROC_FEATURE_1 "p15, 0, %0,  c0,  c1, 1"
#define FREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0,  c0,  c1, 2"
#define FREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0,  c0,  c1, 4"
#define FREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0,  c0,  c1, 5"
#define FREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0,  c0,  c1, 6"
#define FREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0,  c0,  c1, 7"

#define FREG_CP15_INST_FEATURE_0 "p15, 0, %0,  c0,  c2, 0"
#define FREG_CP15_INST_FEATURE_1 "p15, 0, %0,  c0,  c2, 1"
#define FREG_CP15_INST_FEATURE_2 "p15, 0, %0,  c0,  c2, 2"
#define FREG_CP15_INST_FEATURE_3 "p15, 0, %0,  c0,  c2, 3"
#define FREG_CP15_INST_FEATURE_4 "p15, 0, %0,  c0,  c2, 4"

#define FREG_CP15_CACHE_SIZE_ID "p15, 1, %0,  c0,  c0, 0"
#define FREG_CP15_CACHE_LEVEL_ID "p15, 1, %0,  c0,  c0, 1"
#define FREG_CP15_AUXILARY_ID "p15, 1, %0,  c0,  c0, 7"

#define FREG_CP15_CACHE_SIZE_SEL "p15, 2, %0,  c0,  c0, 0"

/* C1 Register Defines */
#define FREG_CP15_SYS_CONTROL "p15, 0, %0,  c1,  c0, 0"
#define FREG_CP15_AUX_CONTROL "p15, 0, %0,  c1,  c0, 1"
#define FREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0,  c1,  c0, 2"

#define FREG_CP15_SECURE_CONFIG "p15, 0, %0,  c1,  c1, 0"
#define FREG_CP15_SECURE_DEBUG_ENABLE "p15, 0, %0,  c1,  c1, 1"
#define FREG_CP15_NS_ACCESS_CONTROL "p15, 0, %0,  c1,  c1, 2"
#define FREG_CP15_VIRTUAL_CONTROL "p15, 0, %0,  c1,  c1, 3"

/* C7 Register Defines */
#define XREG_CP15_NOP "p15, 0, %0,  c7,  c0, 4"

#define FREG_CP15_INVAL_IC_POU_IS "p15, 0, %0,  c7,  c1, 0"
#define FREG_CP15_INVAL_BRANCH_ARRAY_IS "p15, 0, %0,  c7,  c1, 6"

#define FREG_CP15_PHYS_ADDR "p15, 0, %0,  c7,  c4, 0"

#define FREG_CP15_INVAL_IC_POU "p15, 0, %0,  c7,  c5, 0"
#define FREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0,  c7,  c5, 1"

#define FREG_CONTROL_DCACHE_BIT (0X00000001U << 2U)
#define FREG_CONTROL_ICACHE_BIT (0X00000001U << 12U)

unsigned long cpu_get_smp_id(void);
void cpu_mmu_disable(void);
void cpu_mmu_enable(void);
void cpu_tlb_set(volatile unsigned long *);
void cpu_dcache_clean_flush(void);
void cpu_icache_flush(void);
void cpu_vector_set_base(unsigned int addr);

void cpu_dcache_disable();
void cpu_icache_disable();
void cpu_icache_enable();
void cpu_dcache_enable();

s32 cp15_get_cpu_id();
void cp15_set_vector_base(unsigned int addr);
s32 DisableInterrupt();
void EnableInterrupt(s32 level);

#endif /* BSP_ARCH_ARMV8_AARCH32_CP15 */